home *** CD-ROM | disk | FTP | other *** search
- /*
-
-
- dynamic list manager for GCOOPE version 1.0
-
- by Brian Lee Price
-
- Released as Public Domain July, 1994.
-
-
- these routines are the heart of the GCOOPE version 1.0 kernel --
- they provide partial memory management functions for both
- ordered and unordered lists as well as maintaining the lists
- themselves.
-
- Programmer's Note: yes I use goto where it reduces code size
- and doesn't obscure program flow. If you are prejudiced
- against the goto statement, feel free to rewrite your copy
- of the source code without them... just don't ask me to help
- debug it! :)
-
- These routines are for internal kernel use only.
-
- */
-
- /*
- if you haven't examined pcstruct.h yet, do so now. I recommend
- printing it out and keeping it in hand while examining the
- GCOOPE kernel code. Things will get confusing enough without
- complicating matters any.
- */
-
- #include <mem.h>
-
- #include "gcstruct.h"
-
-
-
- /*
-
- This routine searches the given block of length blockLen at
- address blockAdr for all nulls (all 0s). If it is not, this
- function returns FALSE.
-
- */
-
- static boolean nullSrch(char * blockAdr, int blockLen)
- {
-
- do
- {
- if(*blockAdr) return FALSE;
- blockAdr++;
- blockLen--;
- } while(blockLen > 0);
- return TRUE;
- }
-
-
- /*
- FOR KERNEL USE ONLY!
-
- usage:
- newSlotIndex = addItem(&ofa_dynList, elementSize_ofthelist);
-
- this routine adds an item to a dynList type list structure,
- if the list does not exist it will create it.
-
- when calling this routine, listAdr is a pointer to a dynList
- structure type, elemSize is the size of the slots (elements),
- and the index of the new slot is returned normally, a negative
- value is returned on error.
- */
-
- #define LISTADR ((dynList *) listAdr)
-
-
- int addItem(void *listAdr, int elemSize)
- {
- /* setup x to return a negative value on any error */
- int x=-1;
- unsigned oldSize;
- void * newAdr;
- char * ptrA;
-
- if(listAdr==NULL || elemSize<=0) goto end;
-
- if(LISTADR->listPtr==NULL)
- {
- LISTADR->firstFree=1;
- LISTADR->elemSize=elemSize;
- LISTADR->maxElems=MIN_LIST_ADD;
- if(NULL==(LISTADR->listPtr=s_calloc(MIN_LIST_ADD,elemSize)))
- goto end;
- x = 0;
- goto end;
- }
- if(elemSize!=LISTADR->elemSize) goto end;
-
- retry:
- if(LISTADR->firstFree>=LISTADR->maxElems)
- {
- if ((LISTADR->maxElems+MIN_LIST_ADD) >=
- ((MAX_BLOCK_SIZE-(elemSize-1)) / elemSize))
- {
- outOfElems();
- goto retry;
- }
-
- oldSize=LISTADR->maxElems;
- LISTADR->maxElems+=MIN_LIST_ADD;
- if(NULL==(newAdr=s_calloc(LISTADR->maxElems,elemSize))) goto end;
- x=oldSize;
- memcpy(newAdr,LISTADR->listPtr,x*elemSize);
- s_free(LISTADR->listPtr);
- LISTADR->listPtr=newAdr;
- LISTADR->firstFree=x;
- goto end;
- }
- x=LISTADR->firstFree;
- ptrA=LISTADR->listPtr;
- ptrA+= elemSize * LISTADR->firstFree;
- do {
- ptrA+=elemSize;
- } while (++LISTADR->firstFree < LISTADR->maxElems &&
- ! nullSrch(ptrA, elemSize));
-
- end:
- return x;
- }
-
-
-
- /*
- FOR KERNEL USE ONLY!
-
- usage:
- nextFree=rmvItem(&ofa_dynList, indexToElementToFree);
-
- This routine frees up a previously used slot, note that no effort
- is made to reduce the list memory allocation, for that function see
- compactList below.
-
- When calling this routine, listAdr is a pointer to a dynList
- structure type, elemNdx is the index of the element slot to be freed,
- and the routine returns the first free slot index or a negative value
- on any error.
- */
-
- int rmvItem(void *listAdr, int elemNdx)
- {
- char * ptrA;
-
- if(!listAdr || !LISTADR->listPtr
- || (elemNdx>=LISTADR->maxElems) || (elemNdx<0)) return -1;
- if(elemNdx < LISTADR->firstFree)
- LISTADR->firstFree = elemNdx;
- ptrA= LISTADR->listPtr;
- ptrA+= elemNdx * LISTADR->elemSize;
- memset(ptrA,0,LISTADR->elemSize);
- return LISTADR->firstFree;
- }
-
-
- /*
-
- The following routine compacts a list to a multiple of
- MIN_LIST_ADD in size. If sorted is FALSE, the routine will
- find the beginning of the last contiguous free slot area in
- the list. If sorted is TRUE, the routine will fill in empty
- slots with the contents of the next higher slot starting at
- firstFree and moving through the list until the end. In this
- second case, the result is a contiguous list, otherwise it
- will just be a minimum length list preserving current index
- values (leaving internal free slots).
-
-
- */
-
-
- stat compactList(void *listAdr, boolean sorted)
- {
- char * ptrA;
- int last;
-
- if(!listAdr || !LISTADR->listPtr) return FUNCFAIL;
-
- ptrA=LISTADR->listPtr;
- if(!sorted) /* this may be indexed so we can't move elements */
- {
- last=LISTADR->maxElems;
- ptrA+= LISTADR->elemSize * (--last);
- for(;last>= LISTADR->firstFree; last--, ptrA-=LISTADR->elemSize)
- {
- if(!nullSrch(ptrA, LISTADR->elemSize)) break;
- }
- last=(last<LISTADR->firstFree)?LISTADR->firstFree:last;
- last++;
- }
- else /* this isn't indexed so move slots downward until contiguous */
- {
- char * ptrB;
- int current;
-
- ptrA+=LISTADR->firstFree * LISTADR->elemSize;
- ptrB=ptrA;
- current=LISTADR->firstFree;
- while(++current < LISTADR->maxElems)
- {
- ptrB+=LISTADR->elemSize;
- if(nullSrch(ptrB,LISTADR->elemSize)) continue;
- memcpy(ptrA, ptrB, LISTADR->elemSize);
- memset(ptrB,0,LISTADR->elemSize);
- do {
- ptrA+=LISTADR->elemSize;
- LISTADR->firstFree++;
- } while(!nullSrch(ptrA,LISTADR->elemSize));
- }
- last=(LISTADR->firstFree<LISTADR->maxElems)? LISTADR->firstFree+1:
- LISTADR->maxElems;
- }
- if(last % MIN_LIST_ADD) last= ((last/MIN_LIST_ADD)+1) * MIN_LIST_ADD;
- if(last<LISTADR->maxElems)
- {
- LISTADR->maxElems=last;
- LISTADR->listPtr=s_realloc(LISTADR->listPtr, last * LISTADR->elemSize);
- }
- return FUNCOKAY;
- }
-
-
-
-
-
-
-